package com.cl.short_video_java.util;

import com.aliyun.oss.*;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.cl.short_video_java.exception.WebException;
import com.cl.short_video_java.menum.AliProperties;
import com.cl.short_video_java.pojo.SysSetting;
import com.cl.short_video_java.properties.AliOssProperties;
import com.cl.short_video_java.service.OssService;
import com.cl.short_video_java.service.SysSettingService;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @Author 付
 * @Date 2024-11-11 17:18
 * @Version 1.0
 * @description
 * @since 1.0
 */
@Data
@AllArgsConstructor
//固定代码，CV直接使用
@Component
public class AliOssUtil implements OssService {

	@Autowired
	AliOssProperties aliOssProperties;

	private final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
//	private final String BUKET_HOST = "https://oss-chengliang.oss-cn-beijing.aliyuncs.com";

	@Autowired
	SysSettingService sysSettingService;

	/**
	 * 文件上传
	 *
	 * @param bytes      ：传入的文件要转为byte[]
	 * @param objectName ：表示在oss中存储的文件名字。
	 * @return
	 */
	public String upload(byte[] bytes, String objectName) {
		Map<String, String> aliOssSetting = sysSettingService.getAliOssSetting();
		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(aliOssSetting.get(AliProperties.ENDPOINT.getValue())
				, aliOssSetting.get(AliProperties.ACCESS_KEY_ID.getValue())
				, aliOssSetting.get(AliProperties.ACCESS_KEY_SECRET.getValue()));

		try {
			// 创建PutObject请求。
			ossClient.putObject(aliOssSetting.get(AliProperties.BUCKET_NAME.getValue()), objectName, new ByteArrayInputStream(bytes));
		} catch (OSSException oe) {
			throw new WebException(oe.getMessage());
		} catch (ClientException ce) {
			System.out.println("Error Message:" + ce.getMessage());
		} finally {
			if (ossClient != null) {
				ossClient.shutdown();
			}
		}
		//文件访问路径规则 https://BucketName.Endpoint/ObjectName
		StringBuilder stringBuilder = new StringBuilder("https://");
		stringBuilder
				.append(aliOssSetting.get(AliProperties.BUCKET_NAME.getValue()))
				.append(".")
				.append(aliOssSetting.get(AliProperties.ENDPOINT.getValue()))
				.append("/")
				.append(objectName);

		return stringBuilder.toString();
	}

	/**
	 * 具体上传代码
	 *
	 * @param bucket      backet名称
	 * @param path        路径
	 * @param inputStream 文件流
	 * @return
	 */
	private PutObjectResult ossUpload(String bucket,
									  String path,
									  InputStream inputStream,
									  Map<String, String> aliOssSetting) throws IOException {
		OSS ossClient = null;
		PutObjectResult putObjectResult = null;
		try {
			// 创建OSSClient实例。
			ossClient = new OSSClientBuilder().build(aliOssSetting.get(AliProperties.ENDPOINT.getValue())
					, aliOssSetting.get(AliProperties.ACCESS_KEY_ID.getValue())
					, aliOssSetting.get(AliProperties.ACCESS_KEY_SECRET.getValue()));
			// 通过文件流的形式上传文件
			putObjectResult = ossClient.putObject(bucket, path, inputStream);
		} catch (Exception e) {
			//错误处理
			throw new WebException("文件上传失败！");
		} finally {
			//资源关闭
			assert ossClient != null;
			ossClient.shutdown();
		}
		return putObjectResult;
	}

	public String fileUpload(String fileName, String tempFilePath) throws IOException {
		Map<String, String> aliOssSetting = sysSettingService.getAliOssSetting();
		// 用于在OSS上命名，建议格式 ：年月日/文件名.后缀名，此时可以 以时间建立一个文件夹保存上传的图片
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String transformDate = simpleDateFormat.format(new Date());
		String objectName = transformDate + "/" + System.currentTimeMillis() + "_" + fileName;


		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(aliOssSetting.get(AliProperties.ENDPOINT.getValue())
				, aliOssSetting.get(AliProperties.ACCESS_KEY_ID.getValue())
				, aliOssSetting.get(AliProperties.ACCESS_KEY_SECRET.getValue()));

		// 上传文件流。
		InputStream inputStream = new FileInputStream(tempFilePath);
		//ossClient.putObject(bucketName, objectName, inputStream);

		// 设置设置 HTTP 头 里边的 Content-Type
		ObjectMetadata objectMetadata = new ObjectMetadata();
		objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
		objectMetadata.setContentDisposition("inline;filename=" + fileName);
		objectMetadata.setCacheControl("no-cache");
		objectMetadata.setHeader("Pragma", "no-cache");
		objectMetadata.setContentLength(inputStream.available());
		ossClient.putObject(aliOssSetting.get(AliProperties.BUCKET_NAME.getValue()), objectName, inputStream, objectMetadata);

		// 返回一个有时间的链接，
		Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
		String url = ossClient.generatePresignedUrl(aliOssSetting.get(AliProperties.BUCKET_NAME.getValue()), objectName, expiration).toString();
		// 关闭OSSClient。
		ossClient.shutdown();
		return url.split("\\?")[0];
	}

	/**
	 * 解决问题，直接访问上传的图片地址，会让下载而不是直接访问
	 * 设置设置 HTTP 头 里边的 Content-Type
	 * txt 格式经过测试，不需要转换 上传之后就是 text/plain。其他未测试
	 * 已知  如果 Content-Type = .jpeg 访问地址会直接下载，本方法也是解决此问题
	 *
	 * @param FilenameExtension
	 * @return
	 */
	public static String getcontentType(String FilenameExtension) {
		if (FilenameExtension.equalsIgnoreCase(".bmp")) {
			return "image/bmp";
		}
		if (FilenameExtension.equalsIgnoreCase(".gif")) {
			return "image/gif";
		}
		if (FilenameExtension.equalsIgnoreCase(".jpeg") ||
				FilenameExtension.equalsIgnoreCase(".jpg") ||
				FilenameExtension.equalsIgnoreCase(".png")) {
			return "image/jpg";
		}
		if (FilenameExtension.equalsIgnoreCase(".html")) {
			return "text/html";
		}

		if (FilenameExtension.equalsIgnoreCase(".txt")) {
			return "text/plain";
		}
		if (FilenameExtension.equalsIgnoreCase(".vsd")) {
			return "application/vnd.visio";
		}
		if (FilenameExtension.equalsIgnoreCase(".pptx") ||
				FilenameExtension.equalsIgnoreCase(".ppt")) {
			return "application/vnd.ms-powerpoint";
		}
		if (FilenameExtension.equalsIgnoreCase(".docx") ||
				FilenameExtension.equalsIgnoreCase(".doc")) {
			return "application/msword";
		}
		if (FilenameExtension.equalsIgnoreCase(".xml")) {
			return "text/xml";
		}
		return "image/jpg";
	}

	/**
	 * 图片上传
	 *
	 * @param file
	 * @return
	 */
	@Override
	public String upload(MultipartFile file) {
		Map<String, String> aliOssSetting = sysSettingService.getAliOssSetting();
		// 路径拼接
		String dataPath = format.format(new Date());
		// 文件名称生成
		String uuid = UUID.randomUUID().toString().replace("-", "");
		String path = "img/" + dataPath + "/" + uuid + file.getOriginalFilename();

		try {
			// 上传
			ossUpload(aliOssSetting.get(AliProperties.BUCKET_NAME.getValue()), path, file.getInputStream(), aliOssSetting);
		} catch (IOException e) {
			throw new WebException("文件上传失败！" + e.getMessage());
		}
		// 因为 oss 不会返回访问 url 所以我们自己可以拼接一个：
		// 协议（https://） + 域名访问地址（j3-communication.oss-cn-guangzhou.aliyuncs.com） + 自己拼接的路径（xxx/xxx/a.jpg）
		return aliOssSetting.get(AliProperties.IMG_SERVER.getValue()) + "/" + path;
	}
}
